MODULE_NAME='AS16 - Audio Video Zone'
(
    Dev vdvRoom,
    Dev vdvInterRoomComms,
    Dev daRoomTPs[],
    Dev vdvAudioSwitcher,
    Dev vdvVideoSwitcher,
    Dev vdvHDSwitcher,
    Dev vdvAVR,
    Dev vdvTV,
    Integer nAudioOutput,
    Integer nVideoOutput,
    Integer nHDOutput,
    Integer nButtons[],
    Integer nTextChans[],
    Integer nThisRoom,
    Char strRoomName[]
)
(***********************************************************)
(***********************************************************)
(*  FILE_LAST_MODIFIED_ON: 04/04/2006  AT: 11:33:16        *)
(***********************************************************)
(* System Type : NetLinx                                   *)
(***********************************************************)
(* REV HISTORY:                                            *)
(***********************************************************)
(*
    $History: $
*) 
#DEFINE DEBUG
(***********************************************************)
(*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_DEVICE

(***********************************************************)
(*               CONSTANT DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_CONSTANT
cnMaxDebugLen = 200;
cnOff      = 1;
cnSource1  = 2;
cnSource2  = 3;
cnSource3  = 4;
cnSource4  = 5;
cnSource5  = 6;
cnSource6  = 7;
cnSource7  = 8;
cnSource8  = 9;
cnSource9  = 10;
cnSource10 = 11;
cnSource11 = 12;
cnSource12 = 13;
cnSource13 = 14;
cnSource14 = 15;
cnSource15 = 16;
cnSource16 = 17;
cnSource17 = 18;
cnSource18 = 19;
cnSource19 = 20;
cnSource20 = 21;

cnVolUp   = 22;
cnVolDown = 23;
cnVolMute = 24;

cnMaxSources  = 20;

cnSourceLabelChan = 1
cnRoomLabelChan   = 2
cnVolumeChan      = 3

cnRoomVolumeLevelChan = 1
cnRoomVolumeInLevelChan = 2
cnRoomSourceValueLevelChan = 3

(***********************************************************)
(*              DATA TYPE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_TYPE
Structure _sSourceInfo
{
    Integer nEnabled
    Integer nInUse
    Integer nSourceValue
    Integer nAudioInput
    Integer nVideoInput
    Integer nHDInput
    Integer nAVRInput
    Integer nTVInput
    Char    strName[25]
}

(***********************************************************)
(*               VARIABLE DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_VARIABLE
Volatile _sSourceInfo sSourceInfo[cnMaxSources]

Volatile Integer nCurrentSource
Volatile Integer nRoomHasAVR
Volatile Integer nAVROff
Volatile Integer nAVRDirectVol
Volatile Integer nTVOff = 2 // hack.  not sure how i should pass this value in yet but need it.
Volatile Integer nZoneStartVol = 35 // default value
Volatile Integer nZoneFixedVol = 92 // used for audito switcher to avr
Volatile Integer nVolUp
Volatile Integer nVolDown
Volatile Integer nVolMuteToggle
Volatile Integer nVolLevel
Volatile Integer nCurrentVolume
Volatile Integer nRoomMuted

Volatile Integer nTPVolLevel = 249 // hack.  not sure how i should pass this value in yet but need it.


(***********************************************************)
(*               LATCHING DEFINITIONS GO BELOW             *)
(***********************************************************)
DEFINE_LATCHING

(***********************************************************)
(*       MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW           *)
(***********************************************************)
DEFINE_MUTUALLY_EXCLUSIVE

(***********************************************************)
(*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
(***********************************************************)
(* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *)
(* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *)

Define_Call 'DEBUG_OUTPUT' (Integer nLine, Char strData[])
{
    #IF_DEFINED DEBUG
    Char strTempData[200];
    Integer nLen, nCurrentPos;
    
    nLen = Length_String(strData)
    If (nLen < cnMaxDebugLen) // if we can send it in one line go for it.
    {
	Send_String 0,"__FILE__,' Line:',Itoa(nLine),' Zone:',Itoa(nThisRoom),' ',strData";
    }
    Else // otherwise break it up into multiple lines.
    {
	strTempData = Left_String(strData,cnMaxDebugLen);
	Send_String 0,"__FILE__,' Line:',Itoa(nLine),' Zone:',Itoa(nThisRoom),' ',strTempData";
	nCurrentPos = cnMaxDebugLen
	While (nLen > nCurrentPos)
	{
	    strTempData = Mid_String(strData,nCurrentPos,cnMaxDebugLen);
	    nCurrentPos = nCurrentPos + cnMaxDebugLen
	    Send_String 0,"'Continued: ',strTempData";
	}
    }
    #END_IF
}

Define_Call 'SOURCE_OFF'
{
    Stack_Var Integer nI
    
    If (nAudioOutput > 0)
	Send_Command vdvAudioSwitcher,"'AI0O',Itoa(nAudioOutput)"; // audio switcher
    If (nVideoOutput > 0)
	Send_Command vdvVideoSwitcher,"'VI0O',Itoa(nVideoOutput)"; // video switcher
    If (nHDOutput > 0)
	Send_Command vdvHDSwitcher,"'VI0O',Itoa(nHDOutput)"; // video switcher
    If (nRoomHasAVR && nAVROff)
	Do_Push (vdvAVR, nAVROff); // turn avr on to source's input
    If (nTVOff)
	Do_Push (vdvTV, nTVOff); // turn tv on to source's input
    If (nCurrentSource)
    {
	For (nI = 1; nI <= cnMaxSources; nI++)
	{
	    If (sSourceInfo[nI].nSourceValue == nCurrentSource)
	    {
		If (sSourceInfo[nI].nInUse > 0)
		{
		    sSourceInfo[nI].nInUse--
		    Send_Command vdvInterRoomComms,"'INUSE',Itoa(nI),'=',Itoa(sSourceInfo[nI].nInUse)"
		}
		Break;
	    }
	}
    }
    nCurrentSource = 0;
    Send_Level vdvRoom,cnRoomSourceValueLevelChan,0;
    Call 'DEBUG_OUTPUT' (__LINE__, "'SOURCE_OFF'")
    Send_Command vdvInterRoomComms,"'ROOMFB',Itoa(nThisRoom),'=0'"

    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-'"; // clear volume feedback
    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-Off'";
    
    On[vdvRoom,cnOff]
    On[daRoomTPs,nButtons[cnOff]] // turn on the off feedback
    For (nI = 1; nI <= cnMaxSources; nI++) // turn off sources feedback
    {
	Off[daRoomTPs,nButtons[nI+1]]
    }
}

Define_Call 'SOURCE_SELECT' (Integer nSourceIdx)
{
    Stack_Var Integer nPoolID, nI
    
    Call 'DEBUG_OUTPUT' (__LINE__,"'SOURCE_SELECT Start SourceIdx:',Itoa(nSourceIdx)");
    If (sSourceInfo[nSourceIdx].nEnabled)
    {
	If (nAudioOutput > 0)
	{
	    If (nCurrentSource == 0) // zone was off
	    {
		If (!nRoomHasAvr) // no avr so use zone start up volume
		{
		    Send_Command vdvAudioSwitcher,"'SL',Itoa(nAudioOutput),'V',Itoa(nZoneStartVol),'%'"
		}
		Else // Must have an avr and we need a fixed output
		{
		    Send_Command vdvAudioSwitcher,"'SL',Itoa(nAudioOutput),'V',Itoa(nZoneFixedVol),'%'"
		}
	    }
	    Send_Command vdvAudioSwitcher,"'AI',Itoa(sSourceInfo[nSourceIdx].nAudioInput),'O',Itoa(nAudioOutput)"; // audio switcher
	}
	If (nVideoOutput > 0)
	    Send_Command vdvVideoSwitcher,"'VI',Itoa(sSourceInfo[nSourceIdx].nVideoInput),'O',Itoa(nVideoOutput)"; // video switcher
	If (nHDOutput > 0)
	    Send_String vdvHDSwitcher,"'VI',Itoa(sSourceInfo[nSourceIdx].nHDInput),'O',Itoa(nHDOutput)" // HD switcher
	If (nRoomHasAVR > 0)
	{
	    If (nCurrentSource == 0 && nAVRDirectVol && sSourceInfo[nSourceIdx].nAVRInput) // zone was off so turn on avr then set volume
	    {
		Do_Push (vdvAVR, sSourceInfo[nSourceIdx].nAVRInput); // turn avr on to source's input
		Wait 30
		Send_Level vdvAVR,nAVRDirectVol,nZoneStartVol
	    }
	    Else If (sSourceInfo[nSourceIdx].nAVRInput)
	    {
		Do_Push (vdvAVR, sSourceInfo[nSourceIdx].nAVRInput); // turn avr on to source's input
	    }
	}
	If (sSourceInfo[nSourceIdx].nTVInput)
	    Do_Push (vdvTV, sSourceInfo[nSourceIdx].nTVInput); // turn tv on to source's input
	If (nSourceIdx != nCurrentSource)
	{
	    Send_Command vdvInterRoomComms,"'INUSE',Itoa(sSourceInfo[nSourceIdx].nSourceValue),'++'"
	    If (nCurrentSource) // If room was on 
	    {
		If (sSourceInfo[nCurrentSource].nInUse > 0)
		{
		    Send_Command vdvInterRoomComms,"'INUSE',Itoa(sSourceInfo[nCurrentSource].nSourceValue),'--'"
		}
	    }
	}
	nCurrentSource = nSourceIdx;
	Send_Level vdvRoom,cnRoomSourceValueLevelChan,sSourceInfo[nSourceIdx].nSourceValue;;
	Send_Command vdvInterRoomComms,"'ROOMFB',Itoa(nThisRoom),'=',Itoa(sSourceInfo[nSourceIdx].nSourceValue)"
	
	On[vdvRoom,nSourceIdx+1]
	Off[vdvRoom,cnOff]
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off feedback for other sources.
	{
	    If (nI != nSourceIdx)
	    {
		Off[vdvRoom,nI+1]
	    }
	}
	
	If (!nRoomHasAVR || (nRoomHasAVR && nVolLevel))
	{
	    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-',Itoa(nCurrentVolume)";
	}
	Else
	{
	    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'---'";
	}
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-',sSourceInfo[nSourceIdx].strName";
    
	On[daRoomTPs,nButtons[nSourceIdx + 1]] // turn on feedback for currnet source.
	Off[daRoomTPs, nButtons[cnOff]] // turn off the off feedback
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off feedback for other sources.
	{
	    If (nI != nSourceIdx)
	    {
		Off[daRoomTPs,nButtons[nI+1]]
	    }
	}
	Call 'DEBUG_OUTPUT' (__LINE__,"'sSourceInfo[',Itoa(nSourceIdx),'].nSourceValue=',Itoa(sSourceInfo[nSourceIdx].nSourceValue),' nCurrentSource=',Itoa(nCurrentSource)");
    }
    Else
    {
	Call 'DEBUG_OUTPUT' (__LINE__,'Source Not Enabled!')
    }
}

Define_Call 'REBUILD_EVENTS' ()
{
    Stack_Var Integer nI
    Rebuild_Event()
    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnRoomLabelChan]),'-',strRoomName"

    If (nCurrentSource != 0) // zone is on
    {
	If (!nRoomHasAVR || (nRoomHasAVR && nVolLevel))
	{
	    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-',Itoa(nCurrentVolume)" // update volume feedback
	}
	Else
	{
	    Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'---'" // clear volume feedback
	}
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-',sSourceInfo[nCurrentSource].strName";
	Off[daRoomTPs,nButtons[cnOff]] // turn on the off feedback
	On[daRoomTPs,nButtons[nCurrentSource + 1]] // turn on feedback for currnet source.
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off feedback for other sources.
	{
	    If (nI != nCurrentSource)
	    {
		Off[daRoomTPs,nButtons[nI+1]]
	    }
	}
	[daRoomTPs,nButtons[cnVolMute]] = nRoomMuted
    }
    Else // zone off
    {
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-'" // Clear volume feedback
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-Off'";
	On[daRoomTPs,nButtons[cnOff]] // turn on the off feedback
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off sources feedback
	{
	    Off[daRoomTPs,nButtons[nI+1]]
	}
	[daRoomTPs,nButtons[cnVolMute]] = 0
    }
}

Define_Call 'UPDATE_FEEDBACK' (Dev dvDevice)
{
    Local_Var Integer nI
    Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnRoomLabelChan]),'-',strRoomName"

    If (nCurrentSource != 0) // zone is on
    {
	If (!nRoomHasAVR || (nRoomHasAVR && nVolLevel))
	{
	    Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-',Itoa(nCurrentVolume)" // update volume feedback
	}
	Else
	{
	    Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'---'" // clear volume feedback
	}
	Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-',sSourceInfo[nCurrentSource].strName";
	Off[dvDevice,nButtons[cnOff]] // turn on the off feedback
	On[dvDevice,nButtons[nCurrentSource + 1]] // turn on feedback for currnet source.
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off feedback for other sources.
	{
	    If (nI != nCurrentSource)
	    {
		Off[dvDevice,nButtons[nI+1]]
	    }
	}
	[dvDevice,nButtons[cnVolMute]] = nRoomMuted
    }
    Else // zone off
    {
	Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-'" // Clear volume feedback
	Send_Command dvDevice,"'TEXT',Itoa(nTextChans[cnSourceLabelChan]),'-Off'";
	On[dvDevice,nButtons[cnOff]] // turn on the off feedback
	For (nI = 1; nI <= cnMaxSources; nI++) // turn off sources feedback
	{
	    Off[Data.Device,nButtons[nI+1]]
	}
	[dvDevice,nButtons[cnVolMute]] = 0
    }
}

(***********************************************************)
(*                STARTUP CODE GOES BELOW                  *)
(***********************************************************)
DEFINE_START

(***********************************************************)
(*                THE EVENTS GO BELOW                      *)
(***********************************************************)
DEFINE_EVENT

Data_Event[vdvRoom]
{
    Command:
    {
	Stack_Var Char strData[150], strTemp[10], strJunk[10]
	Stack_Var Integer nSource
	
	// Format: SOURCE1=nSourceValue,nAudioInput,nVideoInput,nHDInput,nAVRInput,nTVInput,strName
	// nSourceValue: Unique source identifier
	// nAudioInput: Input used on the audio switcher this zone is connected to
	// nVideoInput: Input used on the video switcher this zone is connected to
	// nHDInput: Input used on the HD switcher this zone is connected to
	// nAVRInput: Channel used to turn on AVR and select the correct input in its module
	// nTVInput: Channel used to turn on TV and select the correct input in its module
	// strName:
		
	strData = Data.Text
	Call 'DEBUG_OUTPUT' (__LINE__,"'Data.Text=',Data.Text");
	If (Find_String(strData,'SOURCE',1))
	{
	    strJunk = Remove_String(strData,'SOURCE',1);
	    nSource = Atoi(strData);
	    sSourceInfo[nSource].nEnabled = 1;
	    strJunk = Remove_String(strData,'=',1);
	    sSourceInfo[nSource].nSourceValue = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].nAudioInput = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].nVideoInput = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].nHDInput = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].nAVRInput = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].nTVInput = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    sSourceInfo[nSource].strName = strData;
	}
	// Format: AVR=Off,VolUp,VolDown,MuteToggle,VolLevel,DirectVolInLevel,StartVol
	Else If (Find_String(strData,'AVR',1))
	{
	    strJunk = Remove_String(strData,'AVR',1);
	    nRoomHasAVR = 1;
	    strJunk = Remove_String(strData,'=',1);
	    nAVROff = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    nVolUp = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    nVolDown = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    nVolMuteToggle = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    nVolLevel = Atoi(strData);
	    strJunk = Remove_String(strData,',',1);
	    nAVRDirectVol = Atoi(strData);
	}
	// Format: AUDIOSWITCHER=StartVol
	Else If (Find_String(strData,'AUDIOSWITCHER',1))
	{
	    strJunk = Remove_String(strData,'AUDIOSWITCHER',1);
	    nRoomHasAVR = 0;
	    strJunk = Remove_String(strData,'=',1);
	    nZoneStartVol = Atoi(strData);
	}
	Else If (Find_String(strData,'REBUILD_EVENTS',1))
	{
	    Call 'REBUILD_EVENTS'
	}
    }
}

Data_Event[vdvInterRoomComms]
{
    Command:
    {
	Stack_Var Char strData[200], strTemp[100], strJunk[10]
	Stack_Var Integer nSource, nRoom, nLevel, nPoolID, nI

	// Format: SWITCHROOM1,2,3,4=nSourceValue
	// Room #: Unique room identifier
	// nSourceValue: Unique source identifier

	strData = Data.Text
	Call 'DEBUG_OUTPUT' (__LINE__,"'Data.Text=',Data.Text");

	If (Find_String(strData,'SWITCHROOM',1))
	{
	    strJunk = Remove_String(strData,'SWITCHROOM',1);
	    strTemp = Remove_String(strData,'=',1);
	    If (strTemp = '0=') // every zone
		nRoom = nThisRoom;
	    Else
		nRoom = Atoi(strTemp);
	    Call 'DEBUG_OUTPUT' (__LINE__,"'nRoom=',Itoa(nRoom)");
	    If (Find_String(strTemp,',',1))
	    {
		While (Find_String(strTemp,',',1))
		{
		    nRoom = Atoi(strTemp);
		    If (nRoom == nThisRoom)
		    {
			nSource = Atoi(strData);
			strTemp = ""; // force exit the while.
			If (nSource > 0 && nSource < cnMaxSources)
			    Call 'SOURCE_SELECT' (nSource);
			Else If (nSource == 0)
			    Call 'SOURCE_OFF'
		    }
		    strJunk = Remove_String(strTemp,',',1);
		}
		nRoom = Atoi(strTemp);
	    }
	    If (nRoom == nThisRoom)
	    {
		nSource = Atoi(strData);
		Call 'DEBUG_OUTPUT' (__LINE__,"'nSource=',Itoa(nSource)");
		If (nSource > 0 && nSource < cnMaxSources)
		    Call 'SOURCE_SELECT' (nSource);
		Else If (nSource == 0)
		    Call 'SOURCE_OFF'
	    }
	}
	Else If (Find_String(strData,'VOLUMEGOTO',1))
	{
	    strJunk = Remove_String(strData,'VOLUMEGOTO',1);
	    strTemp = Remove_String(strData,'=',1);
	    If (strTemp = '0=') // every zone
		nRoom = nThisRoom;
	    Else
		nRoom = Atoi(strTemp);
	    Call 'DEBUG_OUTPUT' (__LINE__,"'nRoom=',Itoa(nRoom)");
	    If (Find_String(strTemp,',',1))
	    {
		While (Find_String(strTemp,',',1))
		{
		    nRoom = Atoi(strTemp);
		    If (nRoom == nThisRoom)
		    {
			nLevel = Atoi(strData);
			strTemp = ""; // force exit the while.
			Call 'DEBUG_OUTPUT' (__LINE__,"'nLevel=',Itoa(nLevel)");
			If (!nRoomHasAvr)
			{
			    Send_Command vdvAudioSwitcher,"'SL',Itoa(nAudioOutput),'V',Itoa(nLevel),'%'"
			}
			Else
			{
			    Send_Level vdvAVR,nAVRDirectVol,nLevel
			}
		    }
		    strJunk = Remove_String(strTemp,',',1);
		}
		nRoom = Atoi(strTemp);
	    }
	}
	Else If (Find_String(strData,'INUSE',1))
	{
	    strJunk = Remove_String(strData,'INUSE',1);
	    nSource = Atoi(strData);
	    strJunk = Remove_String(strData,'=',1);
	    For (nI = 1; nI <= cnMaxSources; nI++)
	    {
		If (nSource = sSourceInfo[nI].nSourceValue)
		{
		    sSourceInfo[nI].nInUse = Atoi(strData);
		    Break;
		}
	    }
	}
	Else If (Find_String(strData,'REBUILD_EVENTS',1))
	{
	    Call 'REBUILD_EVENTS'
	}
    }
}

Data_Event[daRoomTPs]
{
    Online: // update feedback and room name
    {
	Call 'UPDATE_FEEDBACK' (Data.Device)
    }
}

Button_Event[daRoomTPs,nButtons]
{
    Push:
    {
	Stack_Var Integer nLastBtn
	nLastBtn = Get_Last(nButtons)
	Call 'DEBUG_OUTPUT' (__LINE__,"'nLastBtn=',Itoa(nLastBtn)")
	Switch (nLastBtn)
	{
	    Case cnOff:
	    {
		Call 'SOURCE_OFF'
	    }
	    Case cnSource1:
	    Case cnSource2:
	    Case cnSource3:
	    Case cnSource4:
	    Case cnSource5:
	    Case cnSource6:
	    Case cnSource7:
	    Case cnSource8:
	    Case cnSource9:
	    Case cnSource10:
	    Case cnSource11:
	    Case cnSource12:
	    Case cnSource13:
	    Case cnSource14:
	    Case cnSource15:
	    Case cnSource16:
	    Case cnSource17:
	    Case cnSource18:
	    Case cnSource19:
	    Case cnSource20:
	    {            
		Call 'SOURCE_SELECT' (nLastBtn-1)
	    }
	    Case cnVolUp:
	    {
		If (nRoomHasAVR && nVolUp)
		{
		    Do_Push_Timed(vdvAVR,nVolUp,150);
		}
		Else
		{
		    On[vdvAudioSwitcher,(nAudioOutput*3)-2]
		}
	    }
	    Case cnVolDown:
	    {
		If (nRoomHasAVR && nVolDown)
		{
		    Do_Push_Timed(vdvAVR,nVolDown,150);
		}
		Else
		{
		    On[vdvAudioSwitcher,(nAudioOutput*3)-1]
		}
	    }
	    Case cnVolMute:
	    {
		Call 'DEBUG_OUTPUT' (__LINE__,"'nRoomHasAVR:',Itoa(nRoomHasAVR),' nVolMuteToggle:',Itoa(nVolMuteToggle)")
		If (nRoomHasAVR && nVolMuteToggle)
		{
		    Do_Push(vdvAVR,nVolMuteToggle);
		}
		Else
		{
		    [vdvAudioSwitcher,(nAudioOutput*3)] = ![vdvAudioSwitcher,(nAudioOutput*3)]
		}
	    }
	}
    }
    Release:
    {
	Stack_Var Integer nLastBtn
	nLastBtn = Get_Last(nButtons)
	Switch (nLastBtn)
	{
	    Case cnVolUp:
	    {
		If (nRoomHasAVR && nVolUp)
		{
		    Do_Release(vdvAVR,nVolUp);
		}
		Else
		{
		    Off[vdvAudioSwitcher,(nAudioOutput*3)-2]
		}
	    }
	    Case cnVolDown:
	    {
		If (nRoomHasAVR && nVolDown)
		{
		    Do_Release(vdvAVR,nVolDown);
		}
		Else
		{
		    Off[vdvAudioSwitcher,(nAudioOutput*3)-1]
		}
	    }
	}
    }
}

Button_Event[vdvRoom,1]
{
    Push:
    {
	If (nRoomHasAVR && nVolUp)
	{
	    Do_Push_Timed(vdvAVR,nVolUp,150);
	}
	Else
	{
	    On[vdvAudioSwitcher,(nAudioOutput*3)-2]
	}
    }
    Release:
    {
	If (nRoomHasAVR && nVolUp)
	{
	    Do_Release(vdvAVR,nVolUp);
	}
	Else
	{
	    Off[vdvAudioSwitcher,(nAudioOutput*3)-2]
	}
    }
}

Button_Event[vdvRoom,2]
{
    Push:
    {
	If (nRoomHasAVR && nVolDown)
	{
	    Do_Push_Timed(vdvAVR,nVolDown,150);
	}
	Else
	{
	    On[vdvAudioSwitcher,(nAudioOutput*3)-1]
	}
    }
    Release:
    {
	If (nRoomHasAVR && nVolDown)
	{
	    Do_Release(vdvAVR,nVolDown);
	}
	Else
	{
	    Off[vdvAudioSwitcher,(nAudioOutput*3)-1]
	}
    }
}

Level_Event[vdvRoom,cnRoomVolumeInLevelChan]
{
    If (!nRoomHasAvr)
    {
	Send_Command vdvAudioSwitcher,"'SL',Itoa(nAudioOutput),'V',Itoa(Level.Value),'%'"
    }
    Else
    {
	Send_Level vdvAVR,nAVRDirectVol,Level.Value
    }
}

Level_Event[vdvAudioSwitcher,nAudioOutput]
{
    Call 'DEBUG_OUTPUT' (__LINE__,"'nAudioOutput:',Itoa(nAudioOutput),' Level.Value:',Itoa(Level.Value)")
    If (!nRoomHasAVR)
    {
	nCurrentVolume = Type_Cast(Level.Value/2.55);
	Send_Level daRoomTPs,nTPVolLevel,nCurrentVolume;
	Send_Level vdvRoom,cnRoomVolumeLevelChan,nCurrentVolume;
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-',Itoa(nCurrentVolume)";
    }
}

Channel_Event[vdvAudioSwitcher,nVolMuteToggle]
{
    On:
    {
	If (!nRoomHasAVR)
	{
	    On[daRoomTPs,nButtons[cnVolMute]]
	    nRoomMuted = 1
	}
    }
    Off:
    {
	If (!nRoomHasAVR)
	{
	    Off[daRoomTPs,nButtons[cnVolMute]]
	    nRoomMuted = 0
	}
    }
}

Level_Event[vdvAVR,nVolLevel]
{
    If (nRoomHasAVR)
    {
	nCurrentVolume = Level.Value;
	Send_Level daRoomTPs,nTPVolLevel,nCurrentVolume;
	Send_Level vdvRoom,cnRoomVolumeLevelChan,nCurrentVolume;
	Send_Command daRoomTPs,"'TEXT',Itoa(nTextChans[cnVolumeChan]),'-',Itoa(nCurrentVolume)";
    }
}

Channel_Event[vdvAvr,nVolMuteToggle]
{
    On:
    {
	If (nRoomHasAVR)
	{
	    On[daRoomTPs,nButtons[cnVolMute]]
	    nRoomMuted = 1
	}
    }
    Off:
    {
	If (nRoomHasAVR)
	{
	    Off[daRoomTPs,nButtons[cnVolMute]]
	    nRoomMuted = 0
	}
    }
}

(***********************************************************)
(*            THE ACTUAL PROGRAM GOES BELOW                *)
(***********************************************************)
DEFINE_PROGRAM

(***********************************************************)
(*                     END OF PROGRAM                      *)
(*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
(***********************************************************)
